-- 游戏逻辑模块

local skynet = require "skynet"
local base = require "base"
local timetool = require "timetool"
local timer = require "timer"
local filelog = require "filelog"
local tabletool = require "tabletool"
local configdao = require "configdao"

local json = require "cjson"
json.encode_sparse_array(true, 1, 1)

require "dice3enum"

local GameLogic = { }
local service = nil
local tablelogic = nil
local seatlogic = nil

--[Comment]
--init 初始化
function GameLogic.init(caller)
	service = caller
	tablelogic = service:get_logicbyname("tablelogic")
	seatlogic = service:get_logicbyname("seatlogic")
end

--[Comment]
--初始化数据,主要设置游戏状态事件对应的函数
--
function GameLogic.init_data(gameobj, tableobj)
	gameobj.tableobj = tableobj
	gameobj.stateevent[EDICETableState.TABLE_STATE_GAME_START] =  GameLogic.gamestart                         --游戏开始
	gameobj.stateevent[EDICETableState.TABLE_STATE_ONE_GAME_START] = GameLogic.onegamestart                   --一局游戏开始
    gameobj.stateevent[EDICETableState.TABLE_STATE_PLAYER_BET] = GameLogic.playerbet                          --玩家下注
    ---gameobj.stateevent[EDICETableState.TABLE_STATE_OPENDICE_COUNTDOWN] = GameLogic.opendicedown               --开牌倒计时
    gameobj.stateevent[EDICETableState.TABLE_STATE_OPEN_DICE] = GameLogic.opendice                            --执行开牌
    gameobj.stateevent[EDICETableState.TABLE_STATE_HANDLE_OPEN_DICE_RESULT] = GameLogic.handle_opendiceresult  --处理开牌结果
	gameobj.stateevent[EDICETableState.TABLE_STATE_ONE_GAME_END] = GameLogic.onegameend                       --一局游戏结束
	gameobj.stateevent[EDICETableState.TABLE_STATE_ONE_GAME_REAL_END] = GameLogic.onegamerealend              --一局游戏真正结束
    gameobj.stateevent[EDICETableState.TABLE_STATE_GAME_END] = GameLogic.gameend                              --游戏结束

    --初始化游戏记录
    GameLogic.init_game_records(tableobj)

	return true
end

--[Comment]
-- 运行游戏，不断执行状态事件,外部接口
--
function GameLogic.run(gameobj)
	local f = nil
	while true do
        --如果未全部准备，退出
		if gameobj.tableobj.state == EDICETableState.TABLE_STATE_WAIT_ALL_READY then
			break
		end

		f = gameobj.stateevent[gameobj.tableobj.state]  --获得桌子状态对应方法
		if f == nil then
			break
		end
		f(gameobj)  --执行

        --更新心跳时间
        tablelogic.update_table_heart_time(gameobj.tableobj)
	end
end

---------------------------------------------------------
---------------------------------------------------------
--游戏逻辑处理函数
--

--[Comment]
-- TABLE_STATE_GAME_START
-- 游戏开始
-- 游戏开始---一局游戏开始---游戏----一局游戏结束----一局游戏开始---游戏--一局游戏结束--...--游戏结束
-- gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.gamestart(gameobj)
	local tableobj = gameobj.tableobj

	GameLogic.gamestart_inittable(gameobj)
	tableobj.state = EDICETableState.TABLE_STATE_ONE_GAME_START
    --执行完后将调用onegamestart

	--设置桌子已经开局
	tableobj.is_had_start = true

    --上庄列表无人，添加机器人上庄
    if #(tableobj.up_banker_list) == 0 then
        --skynet.call(".robotmgr", "lua", "add_robot_to_table", tableobj.table_service, 1, true)

        local rbt_list = {}
        local down_banker_money = (tableobj.conf.up_banker_money or 50000) - 1
        for _,st in pairs(tableobj.seats) do
            if st.is_robot and st.playerinfo.diamond > down_banker_money then
                table.insert(rbt_list,st.rid)
            end
        end
        ---skynet.call(".robotmgr", "lua", "robot_up_banker", rbt_list, 1, 8, true)
        skynet.sleep(50)
    end

end

--[Comment]
--  一局游戏开始
--  gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.onegamestart(gameobj)
	local tableobj = gameobj.tableobj
    local down_banker_money = (tableobj.conf.up_banker_money or 50000) - 1

    --一初始化游戏
	GameLogic.onegamestart_inittable(gameobj)

    --当前局数 + 1
	tableobj.curr_to_num = tableobj.curr_to_num + 1	

    --获得庄家位置
    local banker_index = tableobj.banker_seat_index or 0
    if banker_index > 0 then    --已有庄家，检测庄家是否满局
        local banker_seat = tableobj.seats[banker_index]
        if not banker_seat or banker_seat.remain_banker_round <= 0 
        or banker_seat.is_disconnected or tableobj.is_down_banker then
            banker_index = 0
            if banker_seat then
                banker_seat.is_banker = false
                banker_seat.remain_banker_round = 0
                banker_seat.cur_upbanker_money = 0
                banker_seat.cur_downbanker_money = 0
            end
        end
    end
    tableobj.is_down_banker = false

    --从上庄列表获取一个庄家
    if banker_index <= 0 then
        while true do
            banker_index = table.remove(tableobj.up_banker_list,1) or 0
            if banker_index > 0 then
                local banker_seat = tableobj.seats[banker_index]
                local curmoney = tablelogic.get_curmoney(banker_seat)
                local cur_upbanker_money = banker_seat.cur_upbanker_money or 0
                if not banker_seat.is_disconnected and cur_upbanker_money <= curmoney 
                    and cur_upbanker_money > down_banker_money then
                    banker_seat.is_banker = true
                    banker_seat.remain_banker_round = tableobj.conf.remain_banker_round or 8
                    tableobj.sys_banker_info.is_banker = false
                    break
                end
            else    --系统做庄
                banker_index = -1
                tableobj.sys_banker_info.is_banker = true
                break
            end
        end
    end

    --通知上庄
    if tableobj.banker_seat_index ~= banker_index then
        tableobj.banker_seat_index = banker_index
        local banker_rid = tableobj.sys_banker_info.rid
        local cur_upbanker_money = 0
        local cur_downbanker_money = 0
        if banker_index > 0 then
            banker_rid = tableobj.seats[banker_index].rid
            tableobj.sys_banker_info.dobanker_round_num = 0
            tableobj.sys_banker_info.cur_upbanker_money = 0
            tableobj.sys_banker_info.cur_downbanker_money = 0
            tableobj.sys_banker_info.playerinfo.coin = 800000
            tableobj.sys_banker_info.playerinfo.diamond = 800000
            cur_upbanker_money = tableobj.seats[banker_index].cur_upbanker_money
            cur_downbanker_money = (tableobj.seats[banker_index].playerinfo.diamond - cur_upbanker_money) + down_banker_money
            tableobj.seats[banker_index].cur_downbanker_money = cur_downbanker_money
        else
            tableobj.sys_banker_info.cur_upbanker_money = tableobj.sys_banker_info.playerinfo.diamond
            cur_upbanker_money = tableobj.sys_banker_info.cur_upbanker_money
            cur_downbanker_money = (tableobj.sys_banker_info.playerinfo.diamond - cur_upbanker_money) + down_banker_money
            tableobj.sys_banker_info.cur_downbanker_money = cur_downbanker_money
        end
        tablelogic.sendmsg_to_alltableplayer(tableobj, "upbankerN", {rid = banker_rid, is_success = true, cur_upbanker_money = cur_upbanker_money})
    elseif banker_index == -1 then
        tableobj.sys_banker_info.dobanker_round_num = (tableobj.sys_banker_info.dobanker_round_num + 1) % 10
    end

    --保存庄家rid
    if  tableobj.banker_seat_index == -1 then
        tableobj.banker_seat_rid = tableobj.sys_banker_info.rid
    else
        tableobj.banker_seat_rid = tableobj.seats[tableobj.banker_seat_index].rid
    end

    --上庄列表人数少于5个，通知机器人上庄
    if #(tableobj.up_banker_list) < 9 then
        local up_robots = {}
        local robot_num = 0
        for _,idx in pairs(tableobj.up_banker_list) do
            local tmp_seat = tableobj.seats[idx]
            if tmp_seat.is_robot then
                up_robots[tmp_seat.rid] = true
                robot_num = robot_num + 1
            end
        end
        if robot_num < 9 then
            local rbt_list = {}
            for _,st in pairs(tableobj.seats) do
                if st.is_robot and not up_robots[st.rid]
                and st.playerinfo.diamond > down_banker_money then
                    local val = base.get_random(1,4)
                    if val == 1 then
                        if st.playerinfo.diamond >= 400000 then
                            table.insert(rbt_list,st.rid)
                        end
                    elseif val == 2 then
                        if st.playerinfo.diamond >= 300000 then
                            table.insert(rbt_list,st.rid)
                        end
                    elseif val == 3 then
                        if st.playerinfo.diamond >= 200000 then
                            table.insert(rbt_list,st.rid)
                        end
                    else
                        table.insert(rbt_list,st.rid)
                    end
                    if #rbt_list > 5 then
                        local x = base.get_random(1,#rbt_list)
                        local y = base.get_random(1,#rbt_list)
                        rbt_list[x],rbt_list[y] = rbt_list[y],rbt_list[x]
                    end
                end
            end
            if #rbt_list == 0 then
                skynet.send(".robotmgr", "lua", "add_robot_to_table", tableobj.table_service, 5, true)
            else
                local dobanker_num = tableobj.sys_banker_info.dobanker_round_num
                --skynet.send(".robotmgr", "lua", "robot_up_banker", rbt_list, 8 - robot_num, dobanker_num)
            end
        end
    end

    --更新特权位，玩家列表
    GameLogic.update_rank_list(gameobj)

    --桌子内保证90%的座位有人,不够则补充机器人,超过且有机器人,则踢掉一些机器人
    --不一次补满，分多次,每次补3~5个
    local max_num = math.floor(tableobj.conf.max_player_num * 0.9)
    local cur_num = tableobj.sitdown_player_num
    if cur_num < max_num then
        local r_num = max_num - cur_num
        local num = base.get_random(3,8)
        if num > r_num then
            num = r_num
        end
        skynet.send(".robotmgr", "lua", "add_robot_to_table", tableobj.table_service, num)
    elseif cur_num > max_num then
        if tableobj.cur_robot_num > 60 then
            local num = cur_num - max_num
            if num > tableobj.cur_robot_num then
                num = tableobj.cur_robot_num
            end
            skynet.send(".robotmgr", "lua", "remove_robots", tableobj.cur_robot_list, num, tableobj.table_service)
        elseif tableobj.cur_robot_num < 50 then
            skynet.send(".robotmgr", "lua", "add_robot_to_table", tableobj.table_service, 5)
        end
    end

    --初始化游戏记录
    GameLogic.onegamestart_init_tablerecord(gameobj)

    --通知client游戏开始
	GameLogic.send_gamestart_notice(gameobj)

    --等待摇骰子
    tableobj.state = EDICETableState.TABLE_STATE_WAIT_PLAYER_BET
	local timer_id = timer.settimer(2.5 * 100, "playerbet")	
	if tableobj.state ~= EDICETableState.TABLE_STATE_WAIT_PLAYER_BET then
		timer.cleartimer(timer_id)
	else
		tableobj.timer_id = timer_id
	end
end

--[Comment]
--
--玩家下注
--
function GameLogic.playerbet(gameobj)
    local tableobj = gameobj.tableobj

    local now = timetool.get_time()
    tableobj.action_timeout_time = now + tableobj.do_bet_timeout

    --设置机器人下注
    local base_score_list = tabletool.deepcopy(tableobj.conf.base_score_list)
    local bet_btn_list = tabletool.deepcopy(tableobj.conf.bet_btn_list)
    local bet_time = tableobj.do_bet_timeout

    --通知玩家下注
    local noticemsg = {
        wait_action_type = EDICEActionType.ACTION_TYPE_BET,
        action_timeout_time = tableobj.action_timeout_time - 1,
    }
    local robot_list = {}
    for _,seat in pairs(tableobj.seats) do
        if seat.state == EDICESeatState.SEAT_STATE_WAIT_BET then
            if seat.is_robot then
                if seat.index ~= tableobj.banker_seat_index then
                    table.insert(robot_list,seat.rid)
                end
            else
                tablelogic.sendmsg_to_tableplayer(seat.rid, "todoN", noticemsg)
            end
        end
    end

    --通知机器人下注
    local sp_rids = { }
    if tableobj.special_seats_rids then
        for _,cur_rid in pairs(tableobj.special_seats_rids) do
           sp_rids[cur_rid] = true
        end
    end
    skynet.send(".robotmgr", "lua", "robot_do_bet", robot_list, bet_btn_list, base_score_list, bet_time, sp_rids)  

    --定时等待
    tableobj.state = EDICETableState.TABLE_STATE_WAIT_OPEN_DICE
	local timer_id = timer.settimer(tableobj.do_bet_timeout * 100, "dodice")	
	if tableobj.state ~= EDICETableState.TABLE_STATE_WAIT_OPEN_DICE then
		timer.cleartimer(timer_id)
	else
		tableobj.timer_id = timer_id
	end

    --随机机器人聊天
    skynet.pcall(GameLogic.robot_ingame_tablechat, tableobj)
end

--
--开牌
--
function GameLogic.opendice(gameobj, is_recall)
    local tableobj = gameobj.tableobj
    local cur_total_bet_list = nil
    local cur_total_bet_num = 0
    local cur_total_bet_cnt = 0
    local is_random = nil
    local is_robot_banker = false

    --系统做庄或机器人做庄，根据玩家下注获取随机结果
    --玩家做庄则根据机器人下注获取随机结果,没有机器人则随机开奖
    local banker_seat = tableobj.seats[tableobj.banker_seat_index]
    if not banker_seat or banker_seat.is_robot then
        cur_total_bet_list = tableobj.cur_player_total_bet_list
        cur_total_bet_num = tableobj.cur_player_total_bet_num
        cur_total_bet_cnt = tableobj.cur_player_total_bet_cnt
        is_robot_banker = true
    else
        cur_total_bet_list = tableobj.cur_robot_total_bet_list
        cur_total_bet_num = tableobj.cur_robot_total_bet_num
        cur_total_bet_cnt = tableobj.cur_robot_total_bet_cnt
    end
    if cur_total_bet_num <= 0 then  --没有下注
        is_random = true
    end

    local opencard_result = {}
    local avg_bet = cur_total_bet_num / cur_total_bet_cnt
    local rand_result = nil
    local ext_prize_result = nil
    local gamename = tablelogic.get_gamename(tableobj)

    --获取已做庄局数
    local banker_round = 0
    local max_banker_round = tableobj.conf.remain_banker_round or 8
    if banker_seat then
        banker_round = max_banker_round - banker_seat.remain_banker_round
    else
        banker_round = tableobj.sys_banker_info.dobanker_round_num or 0
    end
    --filelog.sys_error("----before call----", gamename,cur_total_bet_list,cur_total_bet_num,avg_bet,is_robot_banker,is_random, banker_round)
    --获得随机结果
    rand_result = skynet.call(".slotmgr","lua","get_random_dice_result", gamename,cur_total_bet_list,cur_total_bet_num,avg_bet,is_robot_banker,is_random, banker_round)
    --filelog.sys_error("----after call --------", rand_result)
    opencard_result = tabletool.deepcopy(rand_result.all_cards)

    --检测随机结果
    local is_ok = GameLogic.check_spin_result(tableobj,opencard_result,rand_result)
    if not is_ok then
        return GameLogic.opendice(gameobj,true)
    end

    --计算延时时间,1张牌延时1s
    local delay_time = 2
 
    --通知玩家
    local noticemsg = {
        open_dice = {
            dices = {},  
            allpoints = 0,
        },
    }
    for index, dice in pairs(opencard_result) do
        table.insert(noticemsg.open_dice.dices, dice)
    end
    noticemsg.open_dice.allpoints = rand_result.all_sum
    tablelogic.sendmsg_to_alltableplayer(tableobj, "opendiceN", noticemsg)

    tableobj.rand_result_list = rand_result
    tableobj.opencard_result = opencard_result

    --延时等待
    tableobj.state = EDICETableState.TABLE_STATE_WAIT_HANDLE_OPEN_DICE_RESULT
	local timer_id = timer.settimer(5 * 100, "handle_diceresult")	
	if tableobj.state ~= EDICETableState.TABLE_STATE_WAIT_HANDLE_OPEN_DICE_RESULT then
		timer.cleartimer(timer_id)
	else
		tableobj.timer_id = timer_id
	end
end
--[Comment]
--
--检测随机结果,保证庄家够输
--
function GameLogic.check_spin_result(tableobj, opencard_result, rand_result)
    if tableobj.banker_seat_index == -1 then
        return true
    end
    --总赢取
    local total_win = 0
    local double_num = 1
    local odds_list = tableobj.odds_list
    ---filelog.sys_error("--------odds_list---------", odds_list)
    --基础奖励,押中哪个图标，得对应倍数奖励
    for _,id in pairs(rand_result.prize_ids) do
        local bet_id = id
        if tableobj.cur_total_bet_list[bet_id] then
            local real_id = id * 100 
            total_win = total_win + tableobj.cur_total_bet_list[bet_id] * double_num * (odds_list[real_id] or 0)
        end
    end

    --总赢取不能大于庄家身上金币数
    local banker_seat = tableobj.seats[tableobj.banker_seat_index]
    local banker_money = tablelogic.get_curmoney(banker_seat)
    local init_money = (banker_seat.cur_downbanker_money - tableobj.conf.up_banker_money + 1)
    local real_money = banker_money - init_money + tableobj.cur_total_bet_num
    if total_win > real_money then
        return false
    end
    return true
end

--[Comment]
--
--处理开牌结果
--
function GameLogic.handle_opendiceresult(gameobj)
    local tableobj = gameobj.tableobj
    local rand_result = tableobj.rand_result_list or {}
    local opencard_result = tableobj.opencard_result or {}
    local open_prize_ids = tableobj.rand_result_list.prize_ids or {}
    local double_num = 1    --翻倍数
    for index, value in pairs(tableobj.odds_list) do
        if index >= 2201 and index <= 2206 then
            local status, odd = skynet.pcall(skynet.call, ".slotmgr", "lua", "get_odd_betid", rand_result, index)
            if status then
                tableobj.odds_list[index] = odd
            end
        end
    end
    local odds_list = tableobj.odds_list
    --filelog.sys_error("----handle_opendiceresult----odds_list----", odds_list, rand_result, opencard_result)
    
    for _,seat in pairs(tableobj.seats) do
        if seat.state == EDICESeatState.SEAT_STATE_PLAYING then
            for _,id in pairs(open_prize_ids) do
                local bet_id = id
                ----filelog.sys_error("------seat.cur_bet_list-------", seat.rid, seat.cur_bet_list, bet_id, seat.cur_bet_list[bet_id])
                if seat.cur_bet_list[bet_id] and seat.cur_bet_list[bet_id] > 0 then
                    --local player_id = (id % 10) % 4 + 1
                    --local all_result = rand_result.all_results[player_id] or {}
                    ---local real_id = id * 100 + (all_result.cards_type or 0) * 10 + (all_result.points or 0)
                    seat.curr_score = seat.curr_score + seat.cur_bet_list[bet_id] * double_num * (odds_list[bet_id] or 0)
                    --filelog.sys_error("------seat.curr_score--------", seat.curr_score, bet_id, odds_list[bet_id])
                    table.insert(seat.hit_fruit_list,id)
                end
            end  
        end
    end
    --计算庄家收益
    local banker_seat = tableobj.seats[tableobj.banker_seat_index] or tableobj.sys_banker_info
    --计算下注玩家总赢取,鸿运当头的奖励由系统出
    local cur_total_win = 0
    for _,seat in pairs(tableobj.seats) do
        if seat.state == EDICESeatState.SEAT_STATE_PLAYING and not seat.is_banker and seat.curr_score > 0 then
            cur_total_win = cur_total_win + (seat.curr_score - seat.goodluck_prize_coin)
        end
    end
    local gamename = tablelogic.get_gamename(tableobj)
    local banker_win = skynet.call(".slotmgr","lua","handle_banker_profit",gamename,tableobj.cur_total_bet_num,cur_total_win)
    if tableobj.banker_seat_index == -1 then
        banker_seat.curr_score = banker_win
        if banker_seat.curr_score > 0 then  --赢家抽水，系统庄单独处理
            banker_seat.curr_score = banker_seat.curr_score * (1 - 2 * tableobj.service_fee_rate)
        end
        if tablelogic.is_diamondtable() then
            banker_seat.playerinfo.diamond = banker_seat.playerinfo.diamond + banker_seat.curr_score
        else
            banker_seat.playerinfo.coin = banker_seat.playerinfo.coin + banker_seat.curr_score
        end
    else
        banker_seat.curr_score = banker_seat.curr_score + banker_win 
    end
    
    --等待3s
    tableobj.state = EDICETableState.TABLE_STATE_WAIT_ONE_GAME_END
	local timer_id = timer.settimer(1 * 100, "onegameend")	
	if tableobj.state ~= EDICETableState.TABLE_STATE_WAIT_ONE_GAME_END then
		timer.cleartimer(timer_id)
	else
		tableobj.timer_id = timer_id
	end
end 

--[Comment]
--  一局游戏结束
--  gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.onegameend(gameobj)
    local tableobj = gameobj.tableobj

    --保存结束时间
    tableobj.one_end_time = timetool.get_time()

	--清空计时器
	if tableobj.timer_id > 0 then
		timer.cleartimer(tableobj.timer_id)
		tableobj.timer_id = -1
	end

	--一轮游戏结算
    GameLogic.onegameend_balance(gameobj)

    --更改每个座位总分
	for _, seat in pairs(tableobj.seats) do
		if not seatlogic.is_empty(seat) then
			seat.total_score = seat.total_score + seat.balance_score
		end
	end

    --设置桌子状态为：一局游戏真正结束
	tableobj.state = EDICETableState.TABLE_STATE_ONE_GAME_REAL_END
end

--[Comment]
--  一局游戏真正结束
--  gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.onegamerealend(gameobj)
	local tableobj = gameobj.tableobj

    tableobj.is_onegameend = true
   
    --通知结算金钱变化
    if tablelogic.is_diamondtable() then
        GameLogic.game_balance_diamond(gameobj)
    end

    --保存牌局记录
    GameLogic.onegameend_save_tablerecord(gameobj)
    
    --获得游戏结果
	local noticemsg = GameLogic.get_game_result(gameobj)

    --向机器人服务更新游戏数据
    GameLogic.send_gameinfo_to_robotmgr(gameobj)

    --重置桌子数据,座位数据
	GameLogic.onegameend_inittable(gameobj)

    --发送结算
    local max_win = 0
    local max_win_rolename = nil
    for _,seat in pairs(tableobj.seats) do
        if not seatlogic.is_empty(seat) then
            if max_win < seat.balance_score then
                max_win = seat.balance_score
                max_win_rolename = seat.playerinfo.rolename
            end
            local cur_noticemsg = tabletool.deepcopy(noticemsg)
            local gameresult_list = cur_noticemsg.playergameresultlist
            cur_noticemsg.playergameresultlist = GameLogic.get_allseats_result(tableobj,gameresult_list,seat.index)
            cur_noticemsg.table_gameinfo = tablelogic.copy_table_gameinfo(seat.index)
            tablelogic.sendmsg_to_tableplayer(seat.rid, "gamebalanceN", cur_noticemsg)
        end
    end

    --发送跑马灯
    if max_win >= 100000 then
        tablelogic.send_horseracelamp(max_win_rolename, max_win / 100)
    end

    --根据输赢，发送互动表情
    skynet.pcall(GameLogic.robot_gameend_tablechat, tableobj)
    
    --设置了结束标记,删除桌子
    if tableobj.tableend_flag then
        skynet.call(tableobj.table_service,"lua","cmd","delete",EDICETableDeleteReason.DELETE_REASON_SYSTEM_REQUIRE)
        return
    end

    --踢掉设置了离桌标记,和钱不够的机器人
    for _, seat in pairs(tableobj.seats) do
        if not seatlogic.is_empty(seat) then
            local is_leave = false
		    if seat.is_delayleave then
                is_leave = true
		    elseif seat.is_robot then
                if seat.playerinfo.diamond < 500000 then
                    if seat.playerinfo.diamond >= 50000 then
                        if base.get_random(1,10) == 1 then
                            is_leave = true
                        end
                    elseif seat.playerinfo.diamond >= 20000 then
                        if base.get_random(1,5) == 1 then
                            is_leave = true
                        end
                    elseif seat.playerinfo.diamond >= 10000 then
                        if base.get_random(1,3) == 1 then
                            is_leave = true
                        end
                    elseif seat.playerinfo.diamond >= 5000 then
                        if base.get_random(1,2) == 1 then
                            is_leave = true
                        end
                    else
                        is_leave = true
                    end
                elseif seat.is_banker then
                    local down_banker_money = tableobj.conf.up_banker_money - 1
                    local init_money = seat.cur_downbanker_money + seat.cur_upbanker_money - down_banker_money
                    local win_money = seat.playerinfo.diamond - init_money
                    local max = math.floor(win_money / 30000)
                    local banker_round = tableobj.conf.remain_banker_round - seat.remain_banker_round
                    if win_money > 0 and base.get_random(0,max) > 1 then
                        tableobj.is_down_banker = true
                    elseif win_money > 0 and base.get_random(0,banker_round) > 2 then
                        tableobj.is_down_banker = true
                    elseif banker_round > 4 and base.get_random(0,banker_round) > 2 then
                        tableobj.is_down_banker = true
                    end
                elseif seat.playerinfo.diamond >= 100000 and seat.total_score > 0 then
                    local win_money = seat.total_score
                    local max = math.floor(win_money / 100000)
                    if base.get_random(0,max) > 2 then
                        is_leave = true
                    end
                end
            end
            if is_leave then
                local reason = EStandupReason.STANDUP_REASON_ONSTANDUP
                if not seat.is_robot and seat.is_delayleave and seat.late_total_bet == 0 then
                    reason = EStandupReason.STANDUP_REASON_TENROUND_NOBET or 9
                end
                local rid,coin = seat.rid,tablelogic.get_curmoney(seat)
			    tablelogic.passive_standuptable(tableobj, nil, seat, reason)
			    tablelogic.passive_leavetable(tableobj, rid, coin, nil, reason)
            end
        end
	end
    
    --人数不足，重置桌子状态
    if tableobj.sitdown_player_num < tableobj.min_player_num then
        tableobj.state = EDICETableState.TABLE_STATE_WAIT_PLAYER_SITDOWN
        tableobj.is_had_start = false
        tableobj.up_banker_list = {}
        return
    end

    --上庄列表无人，添加机器人上庄
    if #(tableobj.up_banker_list) == 0 then
        --skynet.call(".robotmgr", "lua", "add_robot_to_table", tableobj.table_service, 5, true)
        skynet.sleep(20)

        local rbt_list = {}
        local down_banker_money = (tableobj.conf.up_banker_money or 50000) - 1
        for _,st in pairs(tableobj.seats) do
            if st.is_robot and st.playerinfo.diamond > down_banker_money then
                table.insert(rbt_list,st.rid)
            end
        end
        --skynet.call(".robotmgr", "lua", "robot_up_banker", rbt_list, 1, 8, true)
    end
    
    --机器人150s未上庄，自动下庄
    local curtime = timetool.get_time()
    for k,v in pairs(tableobj.up_banker_list) do
        local curseat = tableobj.seats[v]
        if curseat and curseat.rid > 0 and curseat.is_robot and curseat.cur_upbanker_time then
            if (curtime - curseat.cur_upbanker_time) > 150 then
                if base.get_random(1,2) == 1 then
                    skynet.send(tableobj.table_service, "lua", "request", "doaction", curseat.rid, {}, {action_type = EDICEActionType.ACTION_TYPE_DOWN_BANKER})
                else
                    curseat.cur_upbanker_time = curtime
                end
            end
        end
    end

    --等待一局开始
    tableobj.state = EDICETableState.TABLE_STATE_WAIT_ONE_GAME_START

    --等待3s
    local delay = 4
    local banker_seat = tableobj.seats[tableobj.banker_seat_index] or tableobj.sys_banker_info
    if banker_seat and banker_seat.last_win_score and banker_seat.last_win_score > 0 then
        delay = 3
    end
	local timer_id = timer.settimer(6 * 100, "onegamestart")	
	if tableobj.state ~= EDICETableState.TABLE_STATE_WAIT_ONE_GAME_START then
		timer.cleartimer(timer_id)
	else
		tableobj.timer_id = timer_id
	end
end

--[Comment]
--  游戏结束
--  gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.gameend(gameobj)
	local tableobj = gameobj.tableobj

	tableobj.state = EDICETableState.TABLE_STATE_UNKNOW   --设置桌子状态为：未知
    if tableobj.game_records ~= nil then
	    tableobj.game_records.end_time = tableobj.end_time or timetool.get_time()
	    tableobj.game_records.final_to_num = tableobj.curr_to_num    --最终局数
        if tableobj.game_records.delete_reason == EDICETableDeleteReason.DELETE_REASON_IN_GAME_DISBAND then
            tableobj.game_records.final_to_num = tableobj.game_records.final_to_num - 1
        end
    end

	--强制踢掉玩家
    if tablelogic.get_sitdown_player_num(tableobj) > 0 then
		tablelogic.leavetableallplayer(tableobj, EStandupReason.STANDUP_REASON_DELETE_TABLE)
		local waits = tabletool.deepcopy(tableobj.waits)
		for rid, waitinfo in pairs(waits) do
			tablelogic.passive_leavetable(tableobj, rid,waitinfo.playerinfo.diamond)
		end
	end

	--检查桌子当前是否能够删除
	if tableobj.delete_table_timer_id <= 0 then
		tableobj.delete_table_timer_id = -1
	end

    tableobj.is_had_start = false

    --倒计时删除,1s
    if tableobj.delete_table_timer_id == -1 then
        tableobj.delete_table_timer_id = timer.settimer(100, "delete_table")
    end
end

------------------------------------------------------------------
----其他方法

--[Comment]
--  坐下
--  gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.on_sitdown_table(gameobj, seat)
    local tableobj = gameobj.tableobj
	if tableobj.delete_table_timer_id > 0 then
		timer.cleartimer(tableobj.delete_table_timer_id)
		tableobj.delete_table_timer_id = -1
	end 
end

--[Comment]
--  等待坐下
--  gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.wait_player_sitdown(gameobj)
	local tableobj = gameobj.tableobj
    if tableobj.sitdown_player_num <= 0 and tableobj.cur_watch_playernum <= 0 then
        if tableobj.delete_table_timer_id > 0 then
			timer.cleartimer(tableobj.delete_table_timer_id)
			tableobj.delete_table_timer_id = -1
		end
        --倒计时删除桌子
 		tableobj.delete_table_timer_id = timer.settimer(10 * 100, "delete_table")
    end
end

--[Comment]
-- 机器人游戏结束后聊天
--
function GameLogic.robot_gameend_tablechat(tableobj)
    --机器人聊天
    local function real_robot_tablechat(tableobj)
        local positive_msgs = {1,2,4}   --积极消息 1飞吻 2干杯 4鲜花
        local passive_msgs = {3,5}      --消极消息 3鸡蛋 5砖头

        local curnum = 0
        local chatnum = base.get_random(1,3)
        local sp_seats = tableobj.special_seats or {}
        for _,seat in pairs(tableobj.seats) do
            if not seatlogic.is_empty(seat) then
                if seat.is_robot and seat.last_win_score ~= 0 
                and not seat.is_banker and base.get_random(1,2) == 1 then
                    local msg_id = nil
                    local target_index = nil
                    if seat.last_win_score > 0 then
                        local idx = base.get_random(1,#positive_msgs)
                        msg_id = positive_msgs[idx]
                    else
                        local idx = base.get_random(1,#passive_msgs)
                        msg_id = passive_msgs[idx]
                    end

                    local r = base.get_random(1,5)
                    if r == 1 then      --发送给庄家
                        target_index = tableobj.banker_seat_index or 0
                    elseif r == 2 then  --发送给非神算子
                        --2/3发给大富豪，1/3其他人
                        if base.get_random(1,3) == 1 then
                            local i = base.get_random(3,6)
                            target_index = sp_seats[i] or 0
                        else
                            target_index = sp_seats[2] or 0
                        end
                    else    --发送给神算子
                        target_index = sp_seats[1] or 0
                    end

                    local targetseat = tableobj.seats[target_index]
                    if targetseat and targetseat.had_ready and seat.rid ~= targetseat.rid and seat.index ~= sp_seats[1] then
                        local msg = {
                            chattype = 5,
                            objrid = targetseat.rid,
                            content = {
                                content = msg_id, 
                                sex = targetseat.playerinfo.sex,
                            },
                        }
                        tablelogic.send_tablechat(tableobj.index, seat.rid, msg)
                        curnum = curnum + 1
                        if curnum >= chatnum then
                            break
                        end
                    end
                end
            end
        end

    end

    --skynet.fork(real_robot_tablechat, tableobj)
end

--[Comment]
-- 机器人游戏中聊天
--
function  GameLogic.robot_ingame_tablechat(tableobj)

    --机器人聊天
    local function real_robot_tablechat(tableobj)
        --所有消息 1飞吻 2干杯 3鸡蛋 4鲜花 5砖头
        local all_msgs = {1,2,3,4,5}   
        local sp_seats = tableobj.special_seats or {}

        local chatnum = base.get_random(1,3)
        for i = 1,chatnum do
            local target_index = nil
            local r = base.get_random(1,5)
            if r == 1 then      --发送给神算子
                target_index = sp_seats[1] or 0
            elseif r == 2 then  --发送给非神算子
                --2/3发给大富豪，1/3其他人
                if base.get_random(1,3) == 1 then
                    local i = base.get_random(3,6)
                    target_index = sp_seats[i] or 0
                else
                    target_index = sp_seats[2] or 0
                end
            else    --发送给庄家
                target_index = tableobj.banker_seat_index or 0
            end

            local targetseat = tableobj.seats[target_index]
            if targetseat and targetseat.had_ready then
                local delay = base.get_random(2,4)
                skynet.sleep(delay * 100)

                local msg_id = base.get_random(1,#all_msgs)
                local msg = {
                    chattype = 5,
                    objrid = targetseat.rid,
                    content = {
                        content = msg_id, 
                        sex = targetseat.playerinfo.sex,
                    },
                }
                tablelogic.send_tablechat(tableobj.index, 1, msg, true)
            end
        end
    end
    
    skynet.fork(real_robot_tablechat, tableobj)
end
-----------------------------
--init类

--[Comment]
-- 第一局游戏开始时，初始化桌子
--
function GameLogic.gamestart_inittable(gameobj)
    --tableobj即table_data
	local tableobj = gameobj.tableobj

    --初始化桌子数据
	tableobj.end_time = 0                       --桌子结束时间
	tableobj.isdeleting = false                 --是否将被删除
	tableobj.is_onegameend = false              --是否一局游戏结束
    tableobj.start_pos = 1
    tableobj.end_pos = 0
    tableobj.prize_id = nil
    tableobj.extprize_item = nil
    tableobj.banker_seat_index = 0
    if tableobj.curr_to_num <= 0 or tableobj.start_time == 0 then
        tableobj.start_time = timetool.get_time() --游戏开始时间
    end

    --保存游戏记录
    if tableobj.game_records then
        tableobj.game_records.start_time = tableobj.start_time
        if not tableobj.game_records.history_prize_list then
            tableobj.game_records.history_prize_list = {}
        end
    end
end

--排序函数
--不稳定的排序会导致错误
--两值相等时必须返回false
local function comp(item1, item2)
    if item1 == nil or item2 == nil then
        return false
    end
    if item1.diamond < item2.diamond then
        return false
    elseif item1.diamond == item2.diamond then
        if item1.win_num < item2.win_num then
            return false
        elseif item1.win_num == item2.win_num then
            if item1.value < item2.value then
                return false
            elseif item1.value == item2.value then
                return false
            end
        end
    end
    return true
end

--交换值
local function swap(arr, i, j)
    local tmp = arr[j]
    arr[j] = arr[i]
    arr[i] = tmp
end

--[Comment]
--  更新排行列表（特权位列表，玩家列表）
--  gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.update_rank_list(gameobj)
    local tableobj = gameobj.tableobj

    --初始化座位
    local last_win_list = {}
    local max_win_seat = nil
    for _,seat in pairs(tableobj.seats) do
        if not seatlogic.is_empty(seat) and seat.had_ready then
            if not seat.is_banker then
                local item = {value = seat.late_total_bet, win_num = seat.win_num, diamond = seat.playerinfo.diamond, seat_index = seat.index, rid = seat.rid}
                table.insert(last_win_list,item)
                if not max_win_seat or max_win_seat.win_num < seat.win_num then
                    max_win_seat = seat
                elseif max_win_seat.win_num == seat.win_num then
                    if max_win_seat.late_total_bet < seat.late_total_bet then
                        max_win_seat = seat
                    elseif max_win_seat.late_total_bet == seat.late_total_bet then
                        if max_win_seat.playerinfo.diamond < item.diamond then
                            max_win_seat = seat
                        end
                    end
                end
            end
       end
    end
    local win_lists = tabletool.deepcopy(last_win_list)
    table.sort(last_win_list,comp)

    --确定特权位
    local i = 1
    local cnt = 0
    local sp_num = (tableobj.special_seats_num or 4)
    local len = #last_win_list
    tableobj.special_seats = {}
    tableobj.special_seats_rids = {}

    --插入神算子
    if max_win_seat then
        table.insert(tableobj.special_seats,max_win_seat.index)
        table.insert(tableobj.special_seats_rids,max_win_seat.rid)
        cnt = cnt + 1
    end
    --插入大富豪
    max_win_seat = max_win_seat or {}
    while (cnt < sp_num and i <= len) do
        if last_win_list[i].rid ~= max_win_seat.rid then
            table.insert(tableobj.special_seats,last_win_list[i].seat_index)
            table.insert(tableobj.special_seats_rids,last_win_list[i].rid)
            cnt = cnt + 1
        end
        i = i + 1
    end
    
    --获取玩家列表
    local index_flags = {}
    tableobj.player_list = {}
    if max_win_seat.index then
        index_flags[max_win_seat.index] = true
        table.insert(tableobj.player_list,max_win_seat.index)
    end
    for _,item in ipairs(last_win_list) do
        if item.rid ~= max_win_seat.rid then
            index_flags[item.seat_index] = true
            table.insert(tableobj.player_list,item.seat_index)
            if #(tableobj.player_list) >= sp_num then
                break
            end
        end
    end

    --插入其他玩家
    local first = 1
    local last = #win_lists
    for i = first + 1,last do
        swap(win_lists, i, first + base.get_random(0,i - first))
    end
    for _,item in ipairs(win_lists) do
        if not index_flags[item.seat_index] then
            table.insert(tableobj.player_list,item.seat_index)
        end
    end
    
end

--[Comment]
-- 每局游戏开始时，初始化桌子
--
function GameLogic.onegamestart_inittable(gameobj)
	local tableobj = gameobj.tableobj
	local now = timetool.get_time()

	tableobj.one_start_time =  now          --本局开始时间
    tableobj.one_end_time = 0               --本局结束时间
    tableobj.action_timeout_time = 0        --当前操作超时时间

    --本局局号
    tableobj.curr_round_code = string.format("%04d",now % 10000)

    --一局结束的标记
	tableobj.is_onegameend = false              --是否一局结束
    tableobj.is_ingame = true                   --是否游戏中
    tableobj.cur_robot_num = 0                  --当前机器人数
    tableobj.cur_robot_list = {}                --当前机器人列表

    --重新获取抽水率
    local gamename = tablelogic.get_gamename(tableobj)
    local status,cur_rate = skynet.pcall(skynet.call, ".slotmgr", "lua", "get_service_fee_rate", gamename)
    if status and cur_rate then
        tableobj.service_fee_rate = tonumber(cur_rate) or 0.03
    end

    --初始化座位
    for _,seat in pairs(tableobj.seats) do
        if not seatlogic.is_empty(seat) and seat.had_ready then
            seatlogic.onegamestart_initseat(seat)
            if seat.is_robot then
                tableobj.cur_robot_num = tableobj.cur_robot_num + 1
                table.insert(tableobj.cur_robot_list,seat.rid)
            end
       end
    end
    
    --重置通用计时器
	if tableobj.timer_id >= 0 then
		timer.cleartimer(tableobj.timer_id)
		tableobj.timer_id = -1
	end

    tableobj.has_resettable = nil
    tableobj.cur_bet_player_num = 0
    tableobj.cur_total_bet_num = 0
    tableobj.remain_total_bet_num = 0
    tableobj.cur_total_bet_cnt = 0
    tableobj.cur_robot_total_bet_num = 0
    tableobj.cur_robot_total_bet_cnt = 0
    tableobj.cur_player_total_bet_num = 0
    tableobj.cur_player_total_bet_cnt = 0
    tableobj.prize_id = nil         --奖励项id
    tableobj.extprize_item = nil    --额外奖励项
    tableobj.start_prize_list = nil --开始奖励项
    tableobj.opencard_result = nil  --开奖结果
    tableobj.cur_total_bet_list = tablelogic.gen_bet_list(tableobj)         --总下注列表
    tableobj.cur_robot_total_bet_list = tablelogic.gen_bet_list(tableobj)   --机器人总下注列表
    tableobj.cur_player_total_bet_list = tablelogic.gen_bet_list(tableobj)  --玩家总下注列表
    tableobj.each_total_bet_cnt_list = {}   --每一个下注项不同底注的下注次数
    tableobj.each_inc_bet_cnt_list = {}     --每一个下注项不同底注的下注次数的变化列表
end

--[Comment]
-- 每局游戏结束时，初始化桌子
--
function GameLogic.onegameend_inittable(gameobj)
	local tableobj = gameobj.tableobj

    tableobj.one_start_time = 0	      --开始时间要先清空，游戏开始时再设置
    tableobj.is_ingame = false        --是否游戏中
    tableobj.curr_round_code = ""
    tableobj.start_pos = tableobj.end_pos or tableobj.start_pos
    tableobj.end_pos = 0
    tableobj.prize_id = nil
    tableobj.extprize_item = nil
    tableobj.start_prize_list = nil
    tableobj.opencard_result = nil  --开奖结果
    tableobj.cur_total_bet_list = {}
    tableobj.each_total_bet_cnt_list = {}
    tableobj.each_inc_bet_cnt_list = {}

    --初始化座位
    for _,seat in pairs(tableobj.seats) do
        if not seatlogic.is_empty(seat) and seat.had_ready then
            seatlogic.onegameend_initseat(seat)
        end
    end

    if tableobj.timer_id >= 0 then
		timer.cleartimer(tableobj.timer_id)
		tableobj.timer_id = -1
	end

end

--[Comment]
-- 初始化游戏记录(桌子创建时便被调用）
--
function GameLogic.init_game_records(tableobj)
    --游戏记录表（记录游戏数据）
	tableobj.game_records = { 
        --固定信息
        table_type = tableobj.table_type,               --桌子类型
		table_uuid = tableobj.uuid,                     --桌子uuid
        create_user_rid = tableobj.create_rid,          --创建者rid
        conf = tableobj.conf or { },                    --桌子配置
        delete_reason = 0,                              --删除原因
		create_time = tableobj.create_time,             --创建时间
        delete_time = 0,                                --删除时间
        start_time = 0,                                 --第一局开始时间
        end_time =  0,                                  --最后一局结束时间
		final_to_num = 0,                               --最终局数
        history_prize_list = {},                        --历史中奖记录
        table_code = tableobj.code,                     --桌号
        banker_win_num = 0,                             --庄家获胜数
        allplayer_win_num = {0,0,0},                    --闲家获胜数
	}

end

--[Comment]
--游戏开始初始化牌局记录
--
function GameLogic.onegamestart_init_tablerecord(gameobj)
    local tableobj = gameobj.tableobj

    --每局信息
    tableobj.game_records.cur_record_id = ""                             --本局记录日志id（log日志文件名）
    tableobj.game_records.curr_to_num = tableobj.curr_to_num or 0        --当前局数
    tableobj.game_records.one_start_time = tableobj.one_start_time or 0  --本局开始时间
    tableobj.game_records.one_end_time = 0                               --本局结束时间
    tableobj.game_records.table_tradeid = ""                             --本局唯一交易id
    tableobj.game_records.players_balance_list = {}                      --本局结算情况
    tableobj.game_records.sys_diamond_start = 0                          --系统开始钻石
    tableobj.game_records.sys_diamond_end = 0                            --系统结束钻石
    tableobj.game_records.user_count = 0                                 --游戏总人数
    tableobj.game_records.banker_seat_index = tableobj.banker_seat_index or 0       --庄家位置
    tableobj.game_records.role_info = { }                                           --玩家信息
    
    --初始化玩家信息
    for _,seat in pairs(tableobj.seats) do
        if GameLogic.is_ingame(gameobj,seat) and not seat.is_robot then
            local item = {
                sex = seat.playerinfo.sex,
                diamond = seat.playerinfo.diamond,
                coin = seat.playerinfo.coin,
                name = seat.playerinfo.rolename,
                logo = seat.playerinfo.logo,
                seat_index = seat.index,
             }
            tableobj.game_records.role_info[seat.rid] = item
        end
    end
                     
    --玩家开始前金钱情况
    tableobj.game_records.diamond_change_list = {}  
    tableobj.game_records.coin_change_list = {}                                 
    for _,seat in pairs(tableobj.seats) do
        if GameLogic.is_ingame(gameobj,seat) and not seat.is_robot then
            local item = { }
            item.gamestart_diamond = seat.playerinfo.diamond
            tableobj.game_records.diamond_change_list[seat.rid] = item
            tableobj.game_records.coin_change_list[seat.rid] = {gamestart_coin = seat.playerinfo.coin}
        end
    end
end

--[Comment]
--游戏结束更新牌局记录
--
function GameLogic.onegameend_save_tablerecord(gameobj)
    local tableobj = gameobj.tableobj

    --修改牌局记录
	if tableobj.game_records ~= nil then
        local game_records = tableobj.game_records
        game_records.user_count = 0
        game_records.one_end_time = tableobj.one_end_time or 0
        game_records.table_tradeid = tableobj.cur_table_tradeid or ""
        game_records.opencard_result = tableobj.rand_result_list
        
        --钻石变化
        local record_id = game_records.table_uuid .. "_"
        record_id = record_id .. game_records.one_start_time .. "_"
        record_id = record_id .. game_records.one_end_time .. "_"
        for _,seat in pairs(tableobj.seats) do
            if GameLogic.is_ingame(gameobj, seat) and not seat.is_robot then
                --金钱变化
                local ditem = game_records.diamond_change_list[seat.rid]
                local citem = game_records.coin_change_list[seat.rid]
                if not ditem then
                    game_records.diamond_change_list[seat.rid] = {gamestart_diamond = seat.playerinfo.diamond}
                    ditem = game_records.diamond_change_list[seat.rid]
                end
                if not citem then
                    game_records.coin_change_list[seat.rid] = {gamestart_coin = seat.playerinfo.coin}
                    citem = game_records.coin_change_list[seat.rid]
                end
                citem.winvalue = seat.playerinfo.coin - citem.gamestart_coin
                ditem.winvalue = seat.playerinfo.diamond - ditem.gamestart_diamond
                citem.gameend_coin = seat.playerinfo.coin
                ditem.gameend_diamond = seat.playerinfo.diamond

                --个人信息
                if not game_records.role_info[seat.rid] then
                    game_records.role_info[seat.rid] = {
                        sex = seat.playerinfo.sex,
                        diamond = seat.playerinfo.diamond,
                        coin = seat.playerinfo.coin,
                        name = seat.playerinfo.rolename,
                        logo = seat.playerinfo.logo,
                        seat_index = seat.index,
                    }
                end

                --结算
                if seat.state == EDICESeatState.SEAT_STATE_PLAYING then
                    if seat.is_robot then
                        game_records.user_count = game_records.user_count - 1
                    else
                        --结算相关
                        local balance_list = { }
                        --玩家rid
                        balance_list.rid = seat.rid
                        --本局下注
                        balance_list.diamond = seat.cur_total_bet
                        --输赢钻石数
                        balance_list.diamond_change = seat.balance_score or 0
                        --下注列表
                        balance_list.cur_bet_list = tabletool.deepcopy(seat.cur_bet_list)
                        --输赢状态，1：赢 0：输
                        if balance_list.diamond_change < 0 then
                            balance_list.state = 0
                        else
                            balance_list.state = 1
                        end
                        table.insert(game_records.players_balance_list,balance_list)
                        game_records.user_count = game_records.user_count + 1
                    end
                end
            end
        end
        record_id = record_id .. os.date("%Y%m%d_%H%M%S",game_records.one_start_time)
        game_records.cur_record_id = record_id

        --保存中奖记录
        local first_record = nil
        local history_prize_list = game_records.history_prize_list
        local maxlen = tableobj.max_history_record_num or 8
        while #history_prize_list >= maxlen do
            first_record = table.remove(history_prize_list,1)
        end
        local record = tabletool.deepcopy(tableobj.opencard_result)
        local record_str = json.encode(record)
        table.insert(history_prize_list,record_str)
	
	    --刷新输赢局数
        -- if first_record then
        --     local first_result = json.decode(first_record) or {}
        --     for _,player_id in pairs(first_result) do
        --         local key = player_id % 10
        --         tableobj.game_records.allplayer_win_num[key] = tableobj.game_records.allplayer_win_num[key] - 1
        --     end
        -- end

        -- if record then
        --     for _,player_id in pairs(record) do
        --         local key = player_id % 10
        --         tableobj.game_records.allplayer_win_num[key] = tableobj.game_records.allplayer_win_num[key] + 1
        --     end
        -- end

        --每隔一天重置历史记录
        local ctm = os.date("*t",tableobj.one_end_time)
        if not tableobj.init_record_day then
            tableobj.init_record_day = os.date("*t",tableobj.start_time).day
        end
        if tableobj.init_record_day ~= ctm.day then
            if tableobj.curr_to_num > 20 then
                tableobj.game_records.banker_win_num = 0
                tableobj.game_records.allplayer_win_num = {0,0,0}
                tableobj.game_records.history_prize_list = {}
            end
            tableobj.init_record_day = ctm.day
        end
	end
    
    --写到日志
    tablelogic.save_table_records(tableobj.game_records)

    --保存玩家历史记录
    local max_history_num = 10  --最大历史记录数
    for _,seat in pairs(tableobj.seats) do
        if not seatlogic.is_empty(seat) then
            local rm_record = nil
            if #(seat.history_record_list) >= max_history_num then
                rm_record = table.remove(seat.history_record_list,1)
            end
            if rm_record then
                if rm_record.curr_score > 0 then
                    if seat.win_num > 0 then
                        seat.win_num = seat.win_num - 1
                    else
                        seat.fail_num = seat.fail_num - 1
                    end
                elseif rm_record.curr_score < 0 then
                    if seat.fail_num > 0 then
                        seat.fail_num = seat.fail_num - 1
                    else
                        seat.win_num = seat.win_num - 1
                    end
                else
                    seat.draw_num = seat.draw_num - 1
                end
                seat.late_total_bet = seat.late_total_bet - rm_record.cur_total_bet
            end
            local cur_record = {
                curr_score = seat.curr_score,
                cur_total_bet = seat.cur_total_bet,
            }
            if cur_record.curr_score > 0 then
                if seat.is_robot and seat.win_num > 16 then
                    seat.fail_num = seat.fail_num + 1
                else
                    seat.win_num = seat.win_num + 1
                end
            elseif cur_record.curr_score < 0 then
                if seat.is_robot and seat.win_num < 10 
                and base.get_random(1,6) == 1 then --机器人1/6概率，输当赢
                    seat.win_num = seat.win_num + 1
                else
                    seat.fail_num = seat.fail_num + 1
                end
            else
                seat.draw_num = seat.draw_num + 1
            end
            seat.late_total_bet = seat.late_total_bet + cur_record.cur_total_bet
            table.insert(seat.history_record_list,cur_record)
        end
    end

end

-----------------------------------------------------------------------------
---check类
--

--[Comment]
--  检查玩家钱是否足够
--  gameobj 游戏对象，{stateevent,tableobj}
--
function  GameLogic.check_player_money(tableobj,seat)
    local min_carry_amount = tableobj.conf.min_carry_amount or 0
    local max_carry_amount = tableobj.conf.max_carry_amount or 0

    if not seat then
        return false
    end

    local money = tablelogic.get_curmoney(seat)
    if money < min_carry_amount or money > max_carry_amount then
        return false
    end

    return true
end

------------------------------------------------------------------------
--通知类方法
--

--[Comment]
--  通知所有玩家游戏开始
--  gameobj 游戏对象，{stateevent,tableobj}
--
 function GameLogic.send_gamestart_notice(gameobj)
	local tableobj = gameobj.tableobj
    local banker_seat = nil
	local noticemsg = { }

    noticemsg.sitdown_player_num = tableobj.sitdown_player_num--玩家数
    noticemsg.banker_seat_index = tableobj.banker_seat_rid    --庄家位置
    if tableobj.banker_seat_index ~= -1 then
        banker_seat = tableobj.seats[tableobj.banker_seat_index] or {}
        noticemsg.curr_to_num = banker_seat.remain_banker_round  --剩余庄家局数
        noticemsg.sitdown_player_num = tableobj.sitdown_player_num - 1
    else
        banker_seat = tableobj.sys_banker_info or {}
        noticemsg.curr_to_num = tableobj.conf.remain_banker_round - banker_seat.dobanker_round_num  --剩余庄家局数
    end
    noticemsg.seat_roleinfos = { }
    noticemsg.seat_gameinfos = { }
    
    --拷贝特权位信息，自己信息，庄家信息并发送
    local sp_num = tableobj.special_seats_num
    for index,seat in pairs(tableobj.seats) do
        if not seatlogic.is_empty(seat) then
            local idx = 1
            local rid_flags = {}
            local cur_noticemsg = tabletool.deepcopy(noticemsg)
            local all_seats_info = tablelogic.copy_all_seats_info(seat.index)
            cur_noticemsg.seat_roleinfos = all_seats_info.seat_roleinfos
            cur_noticemsg.seat_gameinfos = all_seats_info.seat_gameinfos
            cur_noticemsg.special_seats = { }
            for _,rid in ipairs(tableobj.special_seats_rids) do
                --if rid ~= seat.rid then
                    table.insert(cur_noticemsg.special_seats,rid)
                    if #(cur_noticemsg.special_seats) >= sp_num then
                        break
                    end
                --end
            end
            tablelogic.sendmsg_to_tableplayer(seat.rid,"gamestartN", cur_noticemsg)
	end
    end
    
end
	

--[Comment]
--  通知摇骰子
--  gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.send_shakedice_notice(gameobj)
	local tableobj = gameobj.tableobj
	local seat = tableobj.seats[tableobj.banker_seat_index] or tableobj.sys_banker_info
	local noticemsg = {
		rid = seat.rid,
		seat_index = seat.index,
		dice_one = tableobj.dice_one,		
		dice_two = tableobj.dice_two,
	}
	tablelogic.sendmsg_to_alltableplayer(tableobj, "shakediceN", noticemsg)
end

--[Comment]
--  通知所有玩家一局游戏结束
--  gameobj 游戏对象，{stateevent,tableobj}
--
 function GameLogic.send_onegameend_notice(gameobj)
	local tableobj = gameobj.tableobj
	local noticemsg = { }

    noticemsg.table_index = tableobj.index    --桌号
	tablelogic.sendmsg_to_alltableplayer(tableobj,"onegameendN", noticemsg)
 end

 --[Comment]
--  通知所有玩家游戏结束
--  gameobj 游戏对象，{stateevent,tableobj}
--
 function GameLogic.send_gameend_notice(gameobj)
	local tableobj = gameobj.tableobj
	local noticemsg = { }

    noticemsg.table_index = tableobj.index    --桌号
	tablelogic.sendmsg_to_alltableplayer(tableobj,"gameendN", noticemsg)
 end

--向机器人服务更新游戏数据
function GameLogic.send_gameinfo_to_robotmgr(gameobj)
    local tableobj = gameobj.tableobj

    --统计不同底注下注次数
    local bet_score_list = {}
    local total_bet_cnt_list = tableobj.each_total_bet_cnt_list or {}
    if #total_bet_cnt_list ~= 0 then
        for _,item in pairs(total_bet_cnt_list) do
            for score,cnt in pairs(item) do
                bet_score_list[score] = (bet_score_list[score] or 0) + cnt
            end
        end
    end
    
    --统计玩家数
    local total_robot_num = 0
    local total_player_num = 0
    for _,seat in pairs(tableobj.seats) do
        if not seatlogic.is_empty(seat) and seat.had_ready then
            if not seat.is_robot then
                total_player_num = total_player_num + 1
            else
                total_robot_num = total_robot_num + 1
            end
        end
    end

    --通知机器人服务
    skynet.send(".robotmgr", "lua", "update_gameinfo",  bet_score_list, total_player_num, total_robot_num, tableobj.table_service)
end

------------------------------------------------------------------------
---修改数据类
--

--[Comment]
-- 重置桌子数据
--
function GameLogic.reset_tabledata(gameobj)
	local tableobj = gameobj.tableobj

    if tableobj.has_resettable then
        return
    end

    --初始化桌子数据
	tableobj.end_time = 0                       --桌子结束时间
	tableobj.isdeleting = false                 --是否将被删除
	tableobj.is_onegameend = false              --是否一局游戏结束
    tableobj.has_resettable = true
end


-----------------------------------------------------------
--clear类
--

--[Comment]
-- 站起后，删除座位对象
--
function GameLogic.standup_clear_seat(gameobj, seat)
    local tableobj = gameobj.tableobj

    --在上庄列表，则将其清除
    for k,v in pairs(tableobj.up_banker_list) do
        if v == seat.index then
            table.remove(tableobj.up_banker_list,k)
            break
        end
    end

    --在玩家列表，将其清除
    local player_list = tableobj.player_list or {}
    for k,v in pairs(player_list) do
        if v == seat.index then
            table.remove(tableobj.player_list,k)
            break
        end
    end

    --在特权位列表，将其清除
    local special_seats = tableobj.special_seats or {}
    for k,v in pairs(special_seats) do
        if v == seat.index then
            table.remove(tableobj.special_seats,k)
            table.remove(tableobj.special_seats_rids,k)
            break
        end
    end

	seatlogic.clear_seat(seat)
end

---------------------------------------------------------------
---is类
--

--[Comment]
--判断座位对应玩家是否在游戏中
--
function GameLogic.is_ingame(gameobj, seat)
	return (seat.state > EDICESeatState.SEAT_STATE_WAIT_START)
end

------------------------------------------------------------
---get类
--

--[Comment]
--  通知结算信息
--  gameobj 游戏对象，{stateevent,tableobj}
--
function GameLogic.get_game_result(gameobj)
	local tableobj = gameobj.tableobj
    local rand_result = tableobj.rand_result_list

	--通知游戏结算
	local noticemsg = {
		table_index = tableobj.index,                   --桌子id
        create_rid = tableobj.create_rid,               --创建者rid
        create_rolename = tableobj.create_rolename,     --创建者名字
		one_start_time = tableobj.one_start_time,       --本局开始时间
        one_end_time = tableobj.one_end_time,           --本局结束时间
		table_type = tableobj.conf.table_type,          --桌子类型
        banker_seat_index = tableobj.banker_seat_rid,   --庄家位置
        curr_to_num = tableobj.curr_to_num,
        dices = {
            dices = {},
            allpoints = rand_result.all_sum
        },
        opendices_result = {},
		playergameresultlist = { },                     --所有玩家的结算列表
	}

    if rand_result then
        local opendice_result = tabletool.deepcopy(rand_result.prize_ids)
        for index,dice in pairs(rand_result.all_cards) do
            table.insert(noticemsg.dices.dices, dice)
        end
        noticemsg.opendices_result = opendice_result
    end
	
    --获得每个座位结算信息
	local playergameresultitem = nil
	for index, seat in pairs(tableobj.seats) do
	    if not seatlogic.is_empty(seat) then
			playergameresultitem = {   --结算信息
				rid = seat.rid,
                seat_index = seat.index,
				rolename = seat.playerinfo.rolename,
				logo = seat.playerinfo.logo,
				curr_score = seat.balance_score,
	 			total_score = seat.total_score,
                hit_fruit_list = tabletool.deepcopy(seat.hit_fruit_list),
			}
            noticemsg.playergameresultlist[seat.index] = playergameresultitem
		end	
	end

    --系统做庄，放入系统庄家信息
    if tableobj.banker_seat_index == -1 then
        local banker_seat = tableobj.sys_banker_info
        playergameresultitem = {   --结算信息
			rid = banker_seat.rid,
            seat_index = banker_seat.index,
			rolename = banker_seat.playerinfo.rolename,
			logo = banker_seat.playerinfo.logo,
			curr_score = banker_seat.curr_score,
	 		total_score = banker_seat.total_score,
            hit_fruit_list = {},
		}
        noticemsg.playergameresultlist[-1] = playergameresultitem
    end

    return noticemsg
end

--[Comment]
--获得游戏中玩家数
--
function GameLogic.get_ingame_playernum(gameobj)
	local tableobj = gameobj.tableobj
	local playernum = 0
	for _, seat in pairs(tableobj.seats) do
		if GameLogic.is_ingame(gameobj, seat) then
			playernum = playernum + 1
		end
	end
	return playernum
end

--[Comment]
--根据图标id从转盘列表获取一个随机位置
--
function GameLogic.get_random_pos_by_picture_id(tableobj, picture_id, pos_flags)
    pos_flags = pos_flags or {}
    local fruit_index_map_list = tableobj.fruit_index_map_list
    if fruit_index_map_list and fruit_index_map_list[picture_id] then
        local len = #(fruit_index_map_list[picture_id])
        if len > 0 then
            local pos = base.get_random(1,len)
            local real_pos = fruit_index_map_list[picture_id][pos]
            local tmp_pos = pos
            while pos_flags[real_pos] do
                pos = pos % len + 1
                real_pos = fruit_index_map_list[picture_id][pos]
                if tmp_pos == pos then
                    break
                end
            end
            
            return real_pos
        end
    end
end

--
--所得所有座位结算结果
--
function GameLogic.get_allseats_result(tableobj, gameresult_list, self_index)
    local playergameresultlist = {}

    --首先获取特权位的结算
    local idx = 1
    local self_inspseat = false
    local spnum = tableobj.special_seats_num
    for _,seat_index in ipairs(tableobj.special_seats) do
        if gameresult_list[seat_index] then--and seat_index ~= self_index then
            if seat_index == self_index then
                self_inspseat = true
            end
            playergameresultlist[idx] = gameresult_list[seat_index]
            playergameresultlist[idx].seat_index = idx
            idx = idx + 1
            if idx > spnum then
                break
            end
        end
    end

    --获取庄家的结算
    local banker_index = tableobj.banker_seat_index
    if banker_index and gameresult_list[banker_index] then
        playergameresultlist[idx] = gameresult_list[banker_index]
        playergameresultlist[idx].seat_index = idx
        idx = idx + 1
    end

    --获取自己的结算
    if not self_inspseat and self_index and banker_index ~= self_index and gameresult_list[self_index] then
        playergameresultlist[idx] = gameresult_list[self_index]
        playergameresultlist[idx].seat_index = idx
    end

    return playergameresultlist
end

------------------------------------------------------------
---结算类
--

--[Comment]
--@ des 一轮结算
--@ gameobj 游戏对象
--
function GameLogic.onegameend_balance(gameobj)
    local tableobj = gameobj.tableobj
    local banker_index = tableobj.banker_seat_index
    local down_banker_money = (tableobj.conf.up_banker_money or 80000) - 1

    --计算最终得分，并且赢家抽水
    local fee_rate = tableobj.service_fee_rate or 0
    for _,seat in pairs(tableobj.seats) do
        seat.curr_score = seat.curr_score - seat.cur_total_bet
        seat.balance_score = seat.curr_score
        if seat.balance_score > 0 then --赢家抽水
            seat.balance_score = seat.balance_score - math.floor(seat.balance_score * 2 * fee_rate)
        end
    end
    
    --保存记录
    GameLogic.save_records(tableobj)

    if banker_index == -1 then
        tableobj.sys_banker_info.last_win_score = tableobj.sys_banker_info.curr_score
        if tableobj.sys_banker_info.playerinfo.diamond <= down_banker_money then
            tableobj.sys_banker_info.playerinfo.diamond = 800000
        end
        if tableobj.sys_banker_info.playerinfo.coin <= down_banker_money then
            tableobj.sys_banker_info.playerinfo.coin = 800000
        end
        return
    end

    --处理爆庄
    local banker_seat = tableobj.seats[banker_index]
    local curmoney = tablelogic.get_curmoney(banker_seat)
    local cur_downbanker_money = banker_seat.cur_downbanker_money or down_banker_money
    if curmoney + banker_seat.curr_score <= cur_downbanker_money then
        tableobj.is_down_banker = true
    end
end

--[Comment]
--保存记录
--
function GameLogic.save_records(tableobj)
    local opencard_result = tableobj.opencard_result or {}
    local gamename = tablelogic.get_gamename(tableobj)
    skynet.send(".slotmgr","lua","save_prize_records",gamename, opencard_result)
end

--[Comment]
--@ des 钻石场游戏结算
--@ gameobj 游戏对象
--
function GameLogic.game_balance_diamond(gameobj)
    local tableobj = gameobj.tableobj
    local noticemsg = { }
    noticemsg.money_change_list = { }

    --获取需要通知的rid
    local notice_rids = {}
    local brid = tableobj.banker_seat_rid or 0
    local sp_seat_rids = tableobj.special_seats_rids or {}
    for _,rid in pairs(sp_seat_rids) do
        notice_rids[rid] = true
    end
    notice_rids[brid] = true

    local rid_values = { }
    local rid_to_index = { }
    for i,seat in pairs(tableobj.seats) do
        if seat.state == EDICESeatState.SEAT_STATE_PLAYING then
            local change_value = (seat.balance_score or 0)
            if not seat.is_robot then
                rid_values[seat.rid] = {}
                rid_values[seat.rid].beginvalue = seat.playerinfo.diamond
                rid_values[seat.rid].value = change_value
                rid_values[seat.rid].endvalue = rid_values[seat.rid].beginvalue + rid_values[seat.rid].value
                rid_values[seat.rid].real_change = seat.curr_score
                rid_values[seat.rid].total_bet = seat.cur_total_bet
                rid_values[seat.rid].level = seat.playerinfo.level
                rid_to_index[seat.rid] = i
            else
                if notice_rids[seat.rid] then
                    local item = {
                        rid = seat.rid,
                        money_type = EMoneyType.DIAMOND,
                    }
                    seat.playerinfo.diamond = seat.playerinfo.diamond + change_value
                    item.final_value = seat.playerinfo.diamond
                    item.change_value = change_value
                    table.insert(noticemsg.money_change_list,item)
                end
            end
        end
    end

    --通知gate去扣费
    local status,comment = tablelogic.game_balance_diamond(rid_values)
    if not status then
        filelog.sys_error("game balance diamond failed!")
        return false
    else
        filelog.sys_info("game balance diamond ok!", rid_values)
    end
    tableobj.cur_table_tradeid = comment.table_tradeid or ""

    --扣费成功，修改数据
    for rid,rv in pairs(rid_values) do
        local tmpseat = tableobj.seats[rid_to_index[rid]]
        tmpseat.playerinfo.diamond = tmpseat.playerinfo.diamond + rv.value
        if notice_rids[rid] then
            local item = { 
                rid = rid,
                money_type = EMoneyType.DIAMOND, --金钱类型：1金币 2钻石
            }
            item.final_value = rv.endvalue
            item.change_value = rv.value
            table.insert(noticemsg.money_change_list,item)
        end
    end

    --通知客户端
    if #(noticemsg.money_change_list) > 0 then
        for _,seat in pairs(tableobj.seats) do
            if not seatlogic.is_empty(seat) and not seat.is_robot then
                local rv = rid_values[seat.rid]
                local self_noticemsg = tabletool.deepcopy(noticemsg)
                if not notice_rids[seat.rid] and rv then
                    local item = { 
                        rid = seat.rid,
                        money_type = EMoneyType.DIAMOND, --金钱类型：1金币 2钻石
                    }
                    item.final_value = rv.endvalue
                    item.change_value = rv.value
                    table.insert(self_noticemsg.money_change_list,item)
                end
                tablelogic.sendmsg_to_tableplayer(seat.rid, "moneychangeN", self_noticemsg)
            end
        end
    end

    return true
end

---------------------------------------------------------------------
---
--

--[Comment]
--@ des 修复结算数据,保证数据的正确性
--
function GameLogic.fix_balance_values(rid_values)
    if not rid_values then
        return
    end

    local back_values = tabletool.deepcopy(rid_values)
    local negative_values = { }
    local positive_values = { }
    local total_win_value = 0
    local total_lost_value = 0
    for rid,values in pairs(rid_values) do
        if values.endvalue < 0 then
            table.insert(negative_values,rid)
            total_lost_value = total_lost_value + (-values.endvalue)
            values.endvalue = 0
            values.value = -values.beginvalue
        elseif values.endvalue > 0 and values.value > 0 then
            table.insert(positive_values,rid)
            total_win_value = total_win_value + values.value
        end
    end
    
    if total_lost_value <= 0 or total_win_value <= 0 then
        return rid_values
    end

    local total_value = 0
    for i = 1,#positive_values do
        local rid = positive_values[i]
        local values = rid_values[rid]
        local tmp = math.floor(values.value / total_win_value) * total_lost_value
        if i == #positive_values then
            tmp = total_lost_value - total_value
        end
        values.value = values.value - tmp 
        if values.value < 0 then
            tmp = tmp + values.value
            values.value = 0
        end
        values.endvalue = values.value + values.beginvalue
        total_value = total_value + tmp
    end
    
    if total_value == total_lost_value then
        return rid_values
    end

    local tmp = total_lost_value - total_value
    if total_value < total_lost_value then
        for _,rid in pairs(positive_values) do
            local values = rid_values[rid]
            if values.value > 0 then
                if values.value >= tmp then
                    values.value = values.value - tmp
                    values.endvalue = values.value + values.beginvalue
                    break
                else
                    tmp = tmp - values.value
                    values.value = 0
                    values.endvalue = values.beginvalue
                end
            end
        end
        if tmp ~= 0 then
            return back_values
        end
    else
        filelog.print("fix balance values failed!")
        return back_values
    end 

    return rid_values
end

---------------------------------------------------------

return GameLogic

---游戏逻辑----